package app

import (
	"fmt"
	"net"
)

type Udp struct {
	Name          string
	BindLocalPort int
	Conn          *net.UDPConn
	Ref           interface{}
	RecvCall      func(ref interface{}, addr *net.UDPAddr, data []byte, datasize int)
}

func NewUdp(name string, port int, ref interface{}, call func(ref interface{}, addr *net.UDPAddr, data []byte, datasize int)) *Udp {
	return &Udp{Name: name, BindLocalPort: port, Conn: nil, Ref: ref, RecvCall: call}
}
func (u *Udp) Start(sync bool) {
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", u.BindLocalPort))
	if err != nil {
		fmt.Println("ResolveUDPAddr Error:", err)
		return
	}
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		fmt.Println("Listen UDP Error:", err)
		return
	}
	u.Conn = conn
	GetLog().WriteLog(Log_Debug, "UDP Start,Port:", u.BindLocalPort)

	if sync {
		u.receiver()
	} else {
		go func() {
			u.receiver()
		}()
	}
}
func (u *Udp) Stop() {
	u.Conn.Close()

}
func (u *Udp) SendTo(addr *net.UDPAddr, data []byte, datalen int) bool {
	if _, err := u.Conn.WriteToUDP(data[:datalen], addr); err == nil {
		return true
	}
	return false
}
func (u *Udp) SendToAddr(addr string, data []byte, datalen int) bool {
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err == nil {
		return u.SendTo(udpAddr, data, datalen)
	}
	return false
}
func (u *Udp) receiver() {
	buf := make([]byte, 1024*4)
	for {
		n, remoteAddr, err := u.Conn.ReadFromUDP(buf)
		if err != nil {
			fmt.Println("ReadFromUDP Error:", err)
			continue
		}
		u.RecvCall(u.Ref, remoteAddr, buf[:n], n)
	}
}
